﻿using System;
using System.Collections.Generic;
using System.Net;
using System.IO;

namespace vulnanalyzer
{
    class Downloader
    {
        Loading currentLoading;
        long sizeOfPartByte;
        String incompleteDirectory;

        public Downloader(Loading item)
        {
            currentLoading = item;
            sizeOfPartByte = 524288;
            incompleteDirectory = @"./Incomplete";
        }

        /// <summary>
        /// Скачивает часть файла начиная с StartByte до StartByte + Lenght записывает это все сначала в файл имя которого равно хешу,
        /// а потом переименовывает его в _part как только часть закачана
        /// </summary>
        /// <param name="StartByte">номер первого байта</param>
        /// <param name="Lenght">длинна закачиваемой области</param>
        /// <param name="NumberOfPartWithZero">номер второго байта</param>
        public void DownloadPartOfFile(int StartByte, int Lenght, int NumberOfPartWithZero)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(currentLoading.Uri);
            request.Referer = currentLoading.Uri.Authority;
            request.AddRange(StartByte - 1, StartByte + Lenght - 2);
            HttpWebResponse responce = (HttpWebResponse)request.GetResponse();

            Stream input = responce.GetResponseStream();//
            try
            {

                BinaryReader binRead = new BinaryReader(input);
                String buferName = String.Format("{0}.bin", responce.GetHashCode());
                FileInfo currentFileInfo = new FileInfo(String.Format("{0}/inc_{1}/{2}", incompleteDirectory, currentLoading.FileName, buferName));
                FileStream fileStr = currentFileInfo.OpenWrite();
                try
                {
                    BinaryWriter output = new BinaryWriter(fileStr);

                    int bufLen = 2048;
                    byte[] bt = new byte[bufLen];
                    int cnt;
                    do
                    {
                        cnt = binRead.Read(bt, 0, bufLen);
                        if (cnt != 0)
                            output.Write(bt, 0, cnt);
                    }
                    while (cnt != 0);

                    binRead.Close();
                }
                finally
                {
                    fileStr.Close();
                }
                //когда часть полностью принята, переименовывает из хэша в имя + номер части
                currentFileInfo.MoveTo(String.Format("{0}/inc_{1}/{1}_part{2}.bin", incompleteDirectory, currentLoading.FileName, NumberOfPartWithZero));
            }
            finally
            {
                responce.Close();
            }
        }

        /// <summary>
        /// Скачивает указанную часть файла.
        /// </summary>
        /// <param name="NumberOfPartWithZero">Номер части файла</param>
        public void DownloadPartOfFile(int NumberOfPartWithZero)
        {
            DownloadPartOfFile((int)sizeOfPartByte * NumberOfPartWithZero + 1, (int)sizeOfPartByte, NumberOfPartWithZero);
        }

        /// <summary>
        /// Возвращяет целое число частей файла
        /// </summary>
        /// <returns></returns>
        public int GetAmountOfPart()
        {
            long SizeOfFile = GetSizeOfFile();
            long l;
            long ampountOfPartL = Math.DivRem(SizeOfFile, sizeOfPartByte, out l);
            int amountOfPart = (int)ampountOfPartL;
            //количество частей не равно 0
            amountOfPart++;
            return amountOfPart;
        }

        /// <summary>
        /// Возвращяет длину содержимого в байтах
        /// </summary>
        /// <returns></returns>
        public long GetSizeOfFile()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(currentLoading.Uri);

            //авторизация на сервере на всякий случай
            request.Referer = currentLoading.Uri.Authority;

            using (HttpWebResponse responce = (HttpWebResponse)request.GetResponse())
            {
                long returning = responce.ContentLength;
                responce.Close();
                return returning;
            }
        }
    }
}
